DataviewJS 的提取与汇总(汇总标题)
为 DataviewJS 小白手册 提供实践巩固,默认读者已知晓“小白入门 DataviewJS 方法”。
进阶教程:DataviewJS 的翻页与随机
学习关键:
1、分清所用函数属于 JS、Ob 还是 Dv 插件,这样才知道该翻哪个文档、用哪种格式书写。
2、提取与汇总的基础是各种取值操作,通用步骤为“获取数组/对象 - 取出数组项/对象属性”。
- 数组是有序的,各项用索引标识,如
数组[0]
。 - 对象是无序的,各属性用名称标识,如
对象.属性名
或对象[属性名]
。
实例代码获取到数组/对象后,往往只取数组的某项/对象的某个属性。
观察代码在取值前如何获取数组/对象,通过开发控制台查看完整的数组/对象,举一反三,尝试取出一些别的值,很快就能学会如何取出自己想要的值。另:
- 用
moment()
进行时间相关操作需使用 Moment.js 支持的格式。
自定属性使用moment()
为防意外,可写moment(`${ }`)
放花括号里。 - 也许你在同一文档定义多个相同属性,
虽然 有时 1 能借此简便汇总,但长期可能会有意想不到的 问题 1,原理 见此 1。
本文不会介绍和使用类似示例,也提醒各位慎用,除非你知道自己在做什么。
折叠三角可点击展开,点击图片或右键 - 打开图片查看大图。
汇总文档
汇总近一周新建文档
要点:
.groupBy()
后,需用rows
来指代每个组。- 该实例取得的
p.rows.file.link
是数组,需用.join()
转为字符串。
代码
注意:.format('MMDD')
为表格呈现的日期格式,参 Moment.js Format 1 自行修改。
效果:
相关:Dataviewjs的奇技淫巧 #399 3
汇总原文
汇总全文及特定标题下内容
代码见原帖:DataviewJS 汇总全文及特定标题下内容并解决图片显示痛点。
效果:汇总文本,且正常显示图片。左:汇总全文;右:汇总二级标题“任务一”。
[
汇总各级标题为大纲 & 汇总各文档各级标题
前者作用于当前活动文档(单文档),后者作用于路径下文档(多文档)。
要点:
- 通过 Ob API 读取各级标题,通过 JS 方法排版格式。
- 多文档汇总用
.filter(p=> p)
过滤文档中没有标题的文档。
代码
let header = app.metadataCache.getFileCache(app.workspace.getActiveFile()).headings
dv.paragraph(header.map(p=>`${' '.repeat(p.level*2)}- ${p.heading}\n`).reduce((a,b)=>a+b, '')) // 格式、输出
let files = dv.pages(`"文件目录"`)
files.map(async p=> {
let header = app.metadataCache.getFileCache(app.vault.getAbstractFileByPath(p.file.path)).headings.filter(p=> p)
dv.header(6, p.file.link)
dv.paragraph(header.map(p=>`${' '.repeat(p.level*2)}- ${p.heading}\n`).reduce((a,b)=>a+b, '')) // 格式、输出
})
- JS 方法:
.map()
、.repeat()
、.reduce()
、.filter()
- Ob API:
app.metadataCache.getFileCache()
、app.workspace.getActiveFile()
(活动文档)、app.vault.getAbstractFileByPath()
(路径下文档)
效果:单文档 ↔ 多文档
相关:【求助】大纲放到笔记前部;Dataviewjs的奇技淫巧 #136 1
汇总标题下标题
档 1 文本
## 任务一
包括两个任务。
### 扫地
扫地
### 洒水
档 2 文本
## 任务一
包括一个任务。
### 扫地
代码
let term = '任务一'
let files = dv.pages(`"文件目录"`)
let headers = files.map(p=> {
let header = app.metadataCache.getFileCache(app.vault.getAbstractFileByPath(p.file.path)).headings
if (!header) return
let h = []; let b = false
for (let i of header) {
if (b && i.level == 2) b = false; if (i.heading == term && i.level == 2) b = true // 判断是否执行
if (b && i.level == 3) h.push(i.heading) // 执行
}; return h.length == 0 ? false : [p.file.link, h] // 仅当有结果时,返回 p.file.link 和 h
}); dv.table(['文档', term], headers.filter(p=> p))
- JS 方法:
.map()
、.push()
、.filter()
- Ob API:
app.metadataCache.getFileCache()
、app.vault.getAbstractFileByPath()
注意:term = ' '
中的文本为检测条件,判断行的两个 i.level == 2
表明 2 级标题,执行行的 i.level == 3
表明 3 级标题,故此示例代码检测 2 级标题、添加 3 级标题。
效果:也即汇总了文件目录下所有文档中二级标题“任务一”下所有三级标题。
相关:Dataviewjs的奇技淫巧 #340 3
汇总代码块、Callout 等
要点:
- “汇总标题下标题”衍生代码。
- 各截取部分间额外
.concat('\n')
,满足格式渲染所需空行。
代码
同理,将 'code'
改为 'callout'
(小写),即可汇总 Callout。
效果:
彩蛋:汇总块内容
一些短小的内容不想通过井号标题汇总。
要点:想要哪个为第一列,就用哪个 .map( (x, i) => )
。
示例文本
代码
注意:
- 该实例为汇总当前文档“二级标题、<优点>、<缺点>”,缺少相应内容报错是正常的,需修改为你的格式。
.filter(p=> p.level == 2)
限制表体第一项为二级标题,可自行修改。.split('\n\n')
以连续 2 个换行符切片,也即需空段分隔。
自然,如果不是同一块,比如<优点>后的内容间有空行,也是不适用的。.filter(p=> p.startsWith(`<${title}>`))
匹配以<块标题>格式开头的项,不明白可以看看示例文本。
效果:
汇总原文,汇总 YAML
本文是如何汇总的?
1、所有实例放一文件夹下,按分类各自设置 YAML 键 genre
。
2、读取 genre
,格式二级标题;读取各档名,格式三级标题;读取各档全文。自动复制。
3、目录使用“汇总各级标题为大纲”生成。
要点:
- 汇总档和实例放同一文件夹,读取当前文件
.file.folder
,即文件目录;并排除汇总档.file.path
,避免套娃(只是为了偷懒)。 .groupBy()
后,需用rows
来指代每个组。- return 会将值又组合成数组,需用
.join()
重新拆开。
(或许有不需要嵌套的方法,希望知道的人能告诉楼主)
代码
另:
- 本文直接复制,无需在 Dataview 中显示,故没加“汇总全文及特定标题下内容”中处理图片的代码。
- 最初想通过 Templater 插件将文件名 tp 为三级标题,参考了 一种在创建未命名文件并重命名之后自动调用templater模板的方法,虽然本文没用到,但这个帖子的方法很不错,其他场景广泛适用,值得推广学习。
效果:删掉代码块多余的 s,代码执行自动复制,直接粘贴。
汇总 YAML
图片墙书架点图跳转文档
代码见原帖:YAML 可点击 URL 和 Wiki 链了,分享几个兼适的 DataviewJS 点图跳转文档。
要点见 DataviewJS 的翻页与随机 #4“实例 2 格式行”。
效果:
[
[
相关:能否给图片增加跳转链接;Dataviewjs的奇技淫巧 #374
数据透视表
代码见原帖:DataviewJS 数据透视表。
效果:
[
彩蛋:动态查询日期之间或之前,复制结果 MD 表格
要点:
- 需用
Number()
将el3.value
转为数字。提醒:JS 中'3'+1
将输出31
,很奇妙吧。 - Moment.js 需在时间加减操作前使用
.clone()
,避免影响原值。 - 其余要点可参 b 站视频 Dataviewjs动态查询 及阅读本话题顶部链接的进阶教程自行研究。
代码
注意:
- 需自行在同文档 DvJS 代码块外任意位置写上
<span id='MSG' />
,也即效果 GIF 中的。 遇报错
(setting 'innerText')
,先确认写上,鼠标不放在此 span 上,刷新代码块。 - 以第 3 栏优先,3 栏都有值同 1、3 栏有值,执行“前几天”查询。
- 按引入帖要求,读取档名解析为时间,非读取元数据。若想改为读取元数据,可参“汇总近一周新建文档”自行修改。
效果
汇总 TASK
汇总日期前未完成任务
要点:通过 moment().unix()
读取档名解析为秒,进而进行比较。
代码
let files = dv.pages(`"文件目录"`)
.filter(p=> moment(p.file.name).unix() < moment(dv.current().file.name).unix() && !p.completed)
dv.taskList(files.file.tasks)
- JS 方法:
.filter()
、.split()
、.slice()
、.sort()
- Moment.js:
moment()
、unix()
注意:
- 任务本身不存储时间,故无法直接按照任务本身创建时间筛选。通过手动添加内联注释进而筛选为另一种方法,可自行研究。
- 按引入帖要求,读取档名解析为时间,非读取元数据。若想改为读取元数据,可参“汇总近一周新建文档”自行修改。
效果:仅会汇总文件目录下当前文档日期前的未完成任务。
[
相关:Dataviewjs的奇技淫巧 #113 3
彩蛋:横排汇总近三日任务
配合 CSS,得以只需简单的代码,见原帖:Dataview 如何展示最近几天的待办事项 #13 1。
注意:原帖只用到了 Dataview。当然,想用 DvJS 也是可以的。
效果:
学习 DvJS,不耽于 DvJS。
本话题旨在大家看完后都能写出自己的 DataviewJS,额外需求仍请另建话题。
若出现不显示或报错,先尝试刷新代码块或重启 Ob,并**认真阅读各“注意”**下的说明。
错误报告请参 论坛发帖指导2023“求助反馈不重不漏自查表”,提供必要信息。提醒:
- JS 负责生成元素,也即创建内容本身。
- CSS 负责改变样式,也即改变元素的呈现方式。
所以,一般诸如表格间距过大、表格内容行距过大、表格内容有的换行有的不换行等空白字符和换行显示问题(CSS white-space 属性),等问题,可能需要排查主题或 CSS,而非 DataviewJS。
【参考】
DataviewJS的提取与汇总